﻿namespace DCHealthCheck {

    #region Usings
    using DCHealthCheck.Common;
    using DCHealthCheck.DomainModel;
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Management;
    using System.Text; 
    #endregion

    public class ProcessInfoBuilder {

        #region Members
        private readonly ProcessInfo ProcessInfo;

        private readonly ManagementObject WmiObject;

        private readonly DateTime CurrentDCTime; 
        #endregion

        #region Constructors
        private ProcessInfoBuilder() {
        }

        public ProcessInfoBuilder(ProcessInfo processInfo, ManagementObject wmiObject, DateTime currentDCTime)
            : this() {
            if (processInfo == null) {
                throw new ArgumentNullException("processInfo");
            }
            if (wmiObject == null) {
                throw new ArgumentNullException("wmiObject");
            }

            this.ProcessInfo = processInfo;
            this.WmiObject = wmiObject;
            this.CurrentDCTime = currentDCTime;
        } 
        #endregion

        #region Methods
        public ProcessInfo GetProcessInfo() {
            if (WmiObject["ProcessId"] != null) this.ProcessInfo.ProcessId = Convert.ToInt64(WmiObject["ProcessId"]);
            if (WmiObject["ParentProcessId"] != null) this.ProcessInfo.ParentProcessId = Convert.ToInt64(WmiObject["ParentProcessId"]);
            if (WmiObject["Priority"] != null) this.ProcessInfo.Priority = Convert.ToInt32(WmiObject["Priority"]);

            if (WmiObject["CreationDate"] != null) {
                DateTime startDateTime = DateTime.MinValue;
                if (DateTime.TryParseExact(WmiObject["CreationDate"].ToString().Substring(0, 14), "yyyyMMddHHmmss",
                    CultureInfo.CurrentCulture.DateTimeFormat, DateTimeStyles.None, out startDateTime)) {
                    this.ProcessInfo.StartDateTime = startDateTime;
                    TimeSpan elapsedTime = this.CurrentDCTime.Subtract(this.ProcessInfo.StartDateTime);
                    this.ProcessInfo.ElapsedTimeTicks = elapsedTime.Ticks;
                }
            }

            if (WmiObject["CommandLine"] != null) this.ProcessInfo.CommandLine = WmiObject["CommandLine"].ToString();
            if (WmiObject["ExecutablePath"] != null) {
                this.ProcessInfo.ExecutablePath = WmiObject["ExecutablePath"].ToString().Replace("\"", string.Empty).Trim();

                if (!string.IsNullOrWhiteSpace(this.ProcessInfo.ExecutablePath)) {
                    try {
                        if (!this.ProcessInfo.ExecutablePath.Any(x => Path.GetInvalidPathChars().Contains(x))) {
                            this.ProcessInfo.Executable = Path.GetFileName(this.ProcessInfo.ExecutablePath);
                        }
                    }
                    catch { }
                }
            }
            if (WmiObject["KernelModeTime"] != null) this.ProcessInfo.KernelModeTicks = Convert.ToInt64(WmiObject["KernelModeTime"]);
            if (WmiObject["UserModeTime"] != null) this.ProcessInfo.UserModeTicks = Convert.ToInt64(WmiObject["UserModeTime"]);
            if (WmiObject["PageFaults"] != null) this.ProcessInfo.PageFaults = Convert.ToInt64(WmiObject["PageFaults"]);
            if (WmiObject["VirtualSize"] != null) this.ProcessInfo.VirtualMemoryBytes = Convert.ToInt64(WmiObject["VirtualSize"]);
            if (WmiObject["WorkingSetSize"] != null) this.ProcessInfo.WorkingSetBytes = Convert.ToInt64(WmiObject["WorkingSetSize"]);
            if (WmiObject["PrivatePageCount"] != null) this.ProcessInfo.PrivateBytes = Convert.ToInt64(WmiObject["PrivatePageCount"]);
            if (WmiObject["QuotaPagedPoolUsage"] != null) this.ProcessInfo.PagePoolBytes = Convert.ToInt64(WmiObject["QuotaPagedPoolUsage"]);
            if (WmiObject["QuotaNonPagedPoolUsage"] != null) this.ProcessInfo.NonPagePoolBytes = Convert.ToInt64(WmiObject["QuotaNonPagedPoolUsage"]);
            if (WmiObject["HandleCount"] != null) this.ProcessInfo.HandleCount = Convert.ToInt32(WmiObject["HandleCount"]);
            if (WmiObject["ThreadCount"] != null) this.ProcessInfo.ThreadCount = Convert.ToInt32(WmiObject["ThreadCount"]);
            if (WmiObject["ReadTransferCount"] != null) this.ProcessInfo.ReadBytes = Convert.ToInt64(WmiObject["ReadTransferCount"]);
            if (WmiObject["WriteTransferCount"] != null) this.ProcessInfo.WriteBytes = Convert.ToInt64(WmiObject["WriteTransferCount"]);
            if (WmiObject["OtherTransferCount"] != null) this.ProcessInfo.OtherBytes = Convert.ToInt64(WmiObject["OtherTransferCount"]);

            return this.ProcessInfo;
        }

        public override string ToString() {
            if (this.ProcessInfo != null) {
                return this.ProcessInfo.ToString();
            }
            else {
                return string.Empty;
            }
        } 
        #endregion
    }
}
